//=============================================================================
#define GLUT_DISABLE_ATEXIT_HACK
#include <windows.h>
#include <glut.h>

#include <gl/gl.h>
#include <gl/glu.h>

#include <SDL_syswm.h>
#include <vector>
#include <iostream>

#include "direct.h"

#include "CTexture.h"

#include "CBackground_Image.h"
#include "CBackground_MPEG.h"

#include "CFont.h"

//=============================================================================

using namespace std;

//=============================================================================

bool OnLoad_Songs();

//=============================================================================
int Win_Main    = 0;
int Win_Preview = 0;

int CurrentMPEG = 0;
int OldMPEG     = 0;

int ListIndex   = 0;

std::vector<CBackground_MPEG*>       MPEG_List;

CFont       FontControl;

std::vector<CFontLine>      SongList;

int CurrentSong = 0;

int OldCurrentSong = 0;

int SongListStart = 0;

CTexture            Tex_MainPreview;

CTexture            Tex_Fade;

float     FadeAlpha = 0.0f;

int     StartFade = 0;

//-----------------------------------------------------------------------------
bool    AutoSlide   = false;

int     AutoSlideStart = 1;
int     AutoSlideEnd = 5;

int     AutoSlideOldTime = 0;

bool    AutoPick = 0;

//-----------------------------------------------------------------------------
float   FPS_LastTime  = 0;

int     FPS_NumFrames = 0;

//-----------------------------------------------------------------------------
CTexture         Tex_Background;

//=============================================================================
void OnSaveFade() {
    glutSetWindow(Win_Preview);

    glClear(GL_COLOR_BUFFER_BIT);		/* clear the display */

    glViewport(0, 0, 512, 512);

    MPEG_List[OldMPEG]->OnRender();
    FontControl.OnRender_Center(SongList[CurrentSong].Text);

    Tex_Fade.Bind();

	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 512, 512, 0);

    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));

    FadeAlpha = 1.0f;

    StartFade = SDL_GetTicks();
}

//=============================================================================
void OnRender_Main() {
    if(AutoSlide) {
        if(AutoSlideOldTime + 10000 < SDL_GetTicks()) {
            CurrentSong++;

            if(CurrentSong > AutoSlideEnd){
                CurrentSong = AutoSlideStart;
            }

            AutoSlideOldTime = SDL_GetTicks();
        }
    }

    //-----------------------------------
    glutSetWindow(Win_Main);

    FPS_NumFrames++;

    if(SDL_GetTicks() > FPS_LastTime + 1000) {
//        char WinTitle[255];
//        sprintf(WinTitle, "His Light : %d : Auto: %d (%d %d)", FPS_NumFrames, AutoSlide, AutoSlideStart, AutoSlideEnd);
//        glutSetWindowTitle(WinTitle);
        FPS_LastTime = SDL_GetTicks();
        FPS_NumFrames = 0;
    }

    char WinTitle[255];
    sprintf(WinTitle, "His Light : Auto (%d)", AutoSlide);
    glutSetWindowTitle(WinTitle);

    glClear(GL_COLOR_BUFFER_BIT);		/* clear the display */

    Tex_Background.RenderQuad(0, 0, 800, 600);

    Tex_MainPreview.Bind();

    glColor4f(1, 1, 1, 0.5f);
    glBegin(GL_QUADS);
        glTexCoord2f(0, 1); glVertex3f(5,       370,        0);
        glTexCoord2f(1, 1); glVertex3f(5 + 298, 370,        0);
        glTexCoord2f(1, 0); glVertex3f(5 + 298, 370 + 224,  0);
        glTexCoord2f(0, 0); glVertex3f(5,       370 + 224,  0);
    glEnd();
    glColor4f(1, 1, 1, 1);

    int j = 0;
    for(int i = ListIndex;i < MPEG_List.size();i++) {
        if(j > 5) break;

        int tX = ((j % 3) * 150) + 335;
        int tY = ((j / 3) * 111) + 378;

        if(MPEG_List[i]) {
            MPEG_List[i]->Tex_Preview.RenderQuad(tX, tY, 128, 96);
        }

        j++;
    }

    int OffsetY = 64 - (SongListStart * 16);
    int Pos = OffsetY + (CurrentSong * 16);

    if(Pos < 64 || Pos >= 352) {
    }else{
        glDisable(GL_TEXTURE_2D);

        glColor3f(.3, .3, .3);
        glBegin(GL_QUADS);
            glVertex3f(4, OffsetY + (CurrentSong * 16), 0);
            glVertex3f(4 + 776, OffsetY + (CurrentSong * 16), 0);
            glVertex3f(4 + 776, OffsetY + (CurrentSong * 16) + 16, 0);
            glVertex3f(4, OffsetY + (CurrentSong * 16) + 16, 0);
        glEnd();
        glColor3f(1, 1, 1);

        glEnable(GL_TEXTURE_2D);
    }

    OffsetY = 64 - (SongListStart * 16);
    Pos = OffsetY + (AutoSlideStart * 16);

    if(Pos < 64 || Pos >= 352) {
    }else{
        glDisable(GL_TEXTURE_2D);

        glColor3f(0, 0.5, 0);
        glBegin(GL_QUADS);
            glVertex3f(4, OffsetY + (AutoSlideStart * 16), 0);
            glVertex3f(4 + 776, OffsetY + (AutoSlideStart * 16), 0);
            glVertex3f(4 + 776, OffsetY + (AutoSlideStart * 16) + 16, 0);
            glVertex3f(4, OffsetY + (AutoSlideStart * 16) + 16, 0);
        glEnd();
        glColor3f(1, 1, 1);

        glEnable(GL_TEXTURE_2D);
    }

    OffsetY = 64 - (SongListStart * 16);
    Pos = OffsetY + (AutoSlideEnd * 16);

    if(Pos < 64 || Pos >= 352) {
    }else{
        glDisable(GL_TEXTURE_2D);

        glColor3f(0.5, 0, 0);
        glBegin(GL_QUADS);
            glVertex3f(4, OffsetY + (AutoSlideEnd * 16), 0);
            glVertex3f(4 + 776, OffsetY + (AutoSlideEnd * 16), 0);
            glVertex3f(4 + 776, OffsetY + (AutoSlideEnd * 16) + 16, 0);
            glVertex3f(4, OffsetY + (AutoSlideEnd * 16) + 16, 0);
        glEnd();
        glColor3f(1, 1, 1);

        glEnable(GL_TEXTURE_2D);
    }

    OffsetY = 65;

    j = 0;
    for(int i = SongListStart;i < SongList.size();i++) {
        if(j >= 18) break;
        FontControl.OnRender(SongList[i].Text, 12, OffsetY + (j * 16));
        j++;
    }

    glFlush();

    glutPostRedisplay();
    glutSwapBuffers();
}

//=============================================================================
void OnRender_Preview() {
    glutSetWindow(Win_Preview);

    glClear(GL_COLOR_BUFFER_BIT);		/* clear the display */

    glViewport(0, 0, 512, 512);

    MPEG_List[CurrentMPEG]->OnRender();

	if(FadeAlpha > 0) {
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);

        glColor4f(1, 1, 1, FadeAlpha);
        Tex_Fade.Bind();
        glBegin(GL_QUADS);
            glTexCoord2f(0, 1); glVertex3f(0,   0,    0);
            glTexCoord2f(1, 1); glVertex3f(800, 0,    0);
            glTexCoord2f(1, 0); glVertex3f(800, 600,  0);
            glTexCoord2f(0, 0); glVertex3f(0,   600,  0);
        glEnd();
        glColor4f(1, 1, 1, 1);

        if(StartFade + 50 < SDL_GetTicks()) {
            FadeAlpha -= 0.03f;
            StartFade = SDL_GetTicks();
        }

        glDisable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	}

    FontControl.OnRender_Center(SongList[CurrentSong].Text);

    Tex_MainPreview.Bind();

	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 512, 512, 0);

    glViewport(0, 0, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));

    glClear(GL_COLOR_BUFFER_BIT);		/* clear the display */

    Tex_MainPreview.Bind();

    glBegin(GL_QUADS);
        glTexCoord2f(0, 1); glVertex3f(0,   0,    0);
        glTexCoord2f(1, 1); glVertex3f(800, 0,    0);
        glTexCoord2f(1, 0); glVertex3f(800, 600,  0);
        glTexCoord2f(0, 0); glVertex3f(0,   600,  0);
    glEnd();

    //MPEG_List[CurrentMPEG]->OnRender();
    //MPEG_List[OldMPEG]->OnRender_Fade();
    //FontControl.OnRender_Center(SongList[CurrentSong].Text);

    glFlush();

    glutPostRedisplay();
    glutSwapBuffers();
}

//=============================================================================
void OnKeyEvent(unsigned char key, int x, int y) {
    if(key == 'r') {
        SongList.clear();
        OnLoad_Songs();
    }

    if(key == 'q') {
      exit(0);
    }else

    if(key == 'z') {
      ListIndex -= 3;
    }else

    if(key == 'x') {
      ListIndex += 3;
    }

    if(key == 'm') {
      CurrentSong++;
    }

    if(key == 'n') {
      CurrentSong--;
    }

    if(key == 'a') {
        AutoSlide = !AutoSlide;
    }

    if(CurrentSong < 0) {
      CurrentSong = 0;
    }

    if(CurrentSong >= SongList.size()) {
      CurrentSong = SongList.size() - 1;
    }

    if(ListIndex < 0) {
      ListIndex = 0;
    }
}

//-----------------------------------------------------------------------------
bool MouseInBounds(int mX, int mY, int X, int Y, int Width, int Height) {
    if(mX >= X && mX <= X + Width &&
        mY >= Y && mY <= Y + Height) {
            return true;
    }

    return false;
}

//-----------------------------------------------------------------------------
void OnMouseEvent(int button, int state, int x, int y) {
    if(state == GLUT_DOWN) return;

    if(MouseInBounds(x, y, 778, 66, 16, 16)) {
        SongListStart--;
    }

    if(MouseInBounds(x, y, 778, 345, 16, 16)) {
        SongListStart++;
    }

    for(int i = 0;i < 18;i++) {
        if(MouseInBounds(x, y, 4, 64 + (i * 16), 776, 16)) {
            if(button == GLUT_RIGHT_BUTTON) {
                if(!AutoPick) {
                    AutoSlideStart = i + (SongListStart);
                }else{
                    AutoSlideEnd = i + (SongListStart);
                }

                AutoPick = !AutoPick;

                break;
            }else{
                CurrentSong = i + (SongListStart);
                break;
            }
        }
    }

    if(SongListStart < 0) {
        SongListStart = 0;
    }

    if(SongListStart >= SongList.size() - 18) {
        SongListStart = SongList.size() - 18;
    }

    for(int i = 0;i < 6;i++) {
        int tX = ((i % 3) * 150) + 335;
        int tY = ((i / 3) * 111) + 378;

        if(x >= tX && x <= tX + 128 &&
            y >= tY && y <= tY + 96) {
            OnSaveFade();

            OldMPEG = CurrentMPEG;

            CurrentMPEG = ListIndex + i;

            OnSaveFade();

            break;
        }
    }

    if(CurrentMPEG <= 0) {
        CurrentMPEG = 0;
    }

    if(CurrentMPEG >= MPEG_List.size()) {
        CurrentMPEG = MPEG_List.size() - 1;
    }
}

//=============================================================================
bool OnLoad_MPEG() {
	_finddata_t		FileInfo;	//Holds File Information

	//Find the first file, and create a file Handle
	long FileHandle = _findfirst("./mpeg/*.*", &FileInfo);

	//Did we find anything?
	if(FileHandle != -1) {
		_findnext(FileHandle,  &FileInfo); //Yes, move past .. (up) directory
	}else{
		fprintf(stderr, "Main_App::OnInit_Videos > No Videos\n");

		return false;
	}

	//Continue to find each map in the directory
	while(_findnext(FileHandle,  &FileInfo) != -1) {
		char Filename[255];
		sprintf(Filename, "./mpeg/%s", FileInfo.name);

		CBackground_MPEG* tempMPEG = new CBackground_MPEG;
		if(tempMPEG->OnLoad(Filename)) {
			printf("OnInit_MPEG > Video Loaded : %s\n", Filename);

			tempMPEG->OnCleanup();

			MPEG_List.push_back(tempMPEG);
		}else{
			return false;
		}
	}

	//We're done, close the file handle
	_findclose(FileHandle);

	return true;
}

//=============================================================================
bool OnLoad_Songs() {
	_finddata_t		FileInfo;	//Holds File Information

	//Find the first file, and create a file Handle
	long FileHandle = _findfirst("./songs/*.*", &FileInfo);

	//Did we find anything?
	if(FileHandle != -1) {
		_findnext(FileHandle,  &FileInfo); //Yes, move past .. (up) directory
	}else{
		fprintf(stderr, "Main_App::OnInit_Videos > No Videos\n");

		return false;
	}

	while(_findnext(FileHandle,  &FileInfo) != -1) {
		char Filename[255];
		sprintf(Filename, "./songs/%s", FileInfo.name);

		char Buffer[1024];
		Buffer[0] = '\0';

		FILE* FileHandle = fopen(Filename, "r");

		bool Start = false;

        CFontLine FontLine;
        FontLine.Text[0] = '\0';

        SongList.push_back(FontLine);

        while(fgets(Buffer, 1024, FileHandle)) {
            if(Buffer[0] == '.') continue;
            if(Buffer[0] == '\n') continue;
            if(Buffer[0] != '[' && Start) {
                sprintf(FontLine.Text, "%s%s", FontLine.Text, Buffer);
            }

            if(Buffer[0] == '[') {
                if(Start) {
                    SongList.push_back(FontLine);
                    FontLine.Text[0] = '\0';
                }
                Start = true;
            }
        }

        SongList.push_back(FontLine);

		fclose(FileHandle);
	}

	//We're done, close the file handle
	_findclose(FileHandle);
}

//==============================================================================
BOOL CALLBACK SetMonitors(HMONITOR hMonitor, HDC hdc1, LPRECT lprcMonitor, LPARAM data) {
    RECT rc = *lprcMonitor;

    MONITORINFO Info;

    GetMonitorInfo(hMonitor, &Info);

    if(rc.left > 0) {
        glutPositionWindow(rc.left, rc.top);
        glutReshapeWindow(rc.right - rc.left, rc.bottom - rc.top);
    }

    return 1;
}

//==============================================================================
int main(int argc, char* argv[]) {
    SDL_Init(SDL_INIT_EVERYTHING);

    atexit(SDL_Quit);

    SDL_Surface* Surf_Display = SDL_SetVideoMode(512, 512, 16, SDL_HWSURFACE);

    static SDL_SysWMinfo pInfo;
    SDL_VERSION(&pInfo.version);
    SDL_GetWMInfo(&pInfo);

    ShowWindow(pInfo.window, 0);

    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(800, 600);

    Win_Main = glutCreateWindow("His Light");

    glOrtho(0, 800, 600, 0, -1, 1);

    glutDisplayFunc(OnRender_Main);
    glutKeyboardFunc(OnKeyEvent);
    glutMouseFunc(OnMouseEvent);

    HGLRC Window1Context = wglGetCurrentContext();

    glEnable(GL_TEXTURE_2D);

    Win_Preview = glutCreateWindow("Preview");

        glutPositionWindow(680, 50);

        glOrtho(0, 800, 600, 0, -1, 1);

        glutReshapeWindow(800, 600);

        glutDisplayFunc(OnRender_Preview);

        wglShareLists(wglGetCurrentContext(), Window1Context);

        HWND hwnd;

        hwnd = FindWindow("GLUT", "Preview");

        //SetWindowLong(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
        //SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW);

        //SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

    EnumDisplayMonitors(NULL, NULL, SetMonitors, 0);

    glClearColor(0.0, 0.0, 0.0, 0.0);

    glEnable(GL_TEXTURE_2D);

    OnLoad_MPEG();

    if(Tex_Background.OnLoad("./gfx/background.jpg") == false) {
        return false;
    }

    FontControl.OnLoad("./font/treb.font");

    Tex_MainPreview.OnLoad("./gfx/blank.jpg");
    Tex_Fade.OnLoad("./gfx/blank.jpg");

    OnLoad_Songs();

    glutMainLoop();

    return 0;
}

//=============================================================================
